package org.lost.newfeatures;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Arrays;
import java.util.HashMap;
import java.util.IntSummaryStatistics;
import java.util.List;
import java.util.Map;
import java.util.function.Predicate;
import java.util.stream.Collectors;

import javax.swing.JButton;

/**
 * Java 8 Lambda Demo
 * 
 * @author  zhangpeijun[zhangpeijun1024@qq.com]
 * @version  [v1.0.1, 2017年11月15日]
 * @see  [相关类/方法]
 * @since  [产品/模块版本]
 */
public class LambdaDemo {
    
    public void runnable() {
        // old metod
        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("new Thread new Runnable");
            }
        }).start();
        new Thread(() -> System.out.println("new Thead Lambda  expressions ")).start();
        Runnable race1 = new Runnable() {
            @Override
            public void run() {
                // 用Lambda 则不被执行
                System.out.println("Hello world !");
            }
        };
        // 实际新增了一个对象
        race1 = () -> System.out.println("Lambda Hello world !");
        race1.run();
        // 自定义接口: 只支持一个接口方法
        LambdaInterface li = (String name) -> {
            System.out.println("Lambda interface statements.");
            System.out.println("Lambda interface " + name);
        };
        li.run("statements test");
        li = (String name) -> System.out.println("Lambda interface " + name);
        li.run("test");
    }
    
    public void event() {
        // 与runnable方法中定义LambdaInterface接口相同
        JButton show = new JButton("Show");
        show.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                System.out.println("Event handling without lambda expression is boring");
            }
        });
        show.addActionListener((e) -> {
            System.out.println("Light, Camera, Action !! Lambda expressions Rocks");
        });
    }
    
    public void foreachDemo() {
        // Java 8之前：
        List<String> features = Arrays.asList("Lambdas", "Default Method", "Stream API", "Date and Time API");
        for (String feature : features) {
            System.out.println(feature);
        }
        // Java 8之后：
        features = Arrays.asList("Lambdas", "Default Method", "Stream API", "Date and Time API");
        features.forEach(n -> System.out.println(n));
        features.forEach(n -> {
            System.out.println("集合对象：");
            System.out.println(n);
        });
        
    }
    
    public static void filterPre(List<String> names, Predicate<String> condition) {
        for (String name : names) {
            if (condition.test(name)) {
                System.out.println(name + " ");
            }
        }
        /*
         //第二种写法
        names.stream().filter((name) -> (condition.test(name))).forEach((name) -> {
            System.out.println(name + " ");
        });
        //第三种写法
        names.forEach((name) -> {
            if(condition.test(name)) {
                System.out.println(name + " ");
            }
        });
        */
    }
    
    public void filter() {
        List<String> features = Arrays.asList("Lambdas", "Default Method", "Stream API", "Date and Time API");
        filterPre(features, (str) -> str.startsWith("L"));
        //第四种写法
        features.forEach((val) -> {
            if (val.startsWith("D")) {
                System.out.println(val);
            }
        });
        // 第五种写法
        Predicate<String> starWith = (str) -> str.startsWith("L");
        features.stream().filter(starWith).forEach((name) -> {
            System.out.println(name + " ");
        });
        // 第六种写法,组合Predicate
        System.out.println("====================");
        Predicate<String> startsWithJ = (n) -> n.startsWith("D");
        Predicate<String> endWith = (n) -> n.endsWith("I");
        features.stream().filter(startsWithJ.and(endWith)).forEach((name) -> {
            System.out.println(name);
        });
    }
    
    public void map() {
        List<Integer> cost = Arrays.asList(100, 200, 300, 400, 500);
        // 每个值*2输出
        cost.stream().map((val) -> val * 2).forEach(System.out::println);
        //cost.forEach((n) -> {System.out.println(n);});
        // *0.12 再叠加 . (sum, val) -> sum + val累加求值？？？
        double bill = cost.stream().map((val) -> val + .12 * val).reduce((sum, val) -> sum + val).get();
        System.out.println("Total : " + bill);
        Map<String, String> hsMap = new HashMap<String, String>();
    }
    
    public void strDemo() {
        // 创建一个字符串列表，每个字符串长度大于2
        List<String> strList = Arrays.asList("L", "Default Method", "S", "Date and Time API");
        List<String> filtered = strList.stream().filter(x -> x.length() > 2).collect(Collectors.toList());
        System.out.printf("old = %s %n", strList);
        System.out.printf("filtered = %s %n", filtered);
        
        // 转换成大写
        System.out.println(strList.stream().map(x -> x.toUpperCase()).collect(Collectors.toList()));
    }
    
    public void collection(){
        // 用所有不同的数字创建一个正方形列表 distinct去重
        List<Integer> numbers = Arrays.asList(9, 10, 3, 4, 7, 3, 4);
        List<Integer> distinct = numbers.stream().map( i -> i*i).distinct().collect(Collectors.toList());
        System.out.printf("Original List : %s,  Square Without duplicates : %s %n", numbers, distinct);
        //获取数字的个数、最小值、最大值、总和以及平均值
        List<Integer> primes = Arrays.asList(2, 3, 5, 7, 11, 13, 17, 19, 23, 29);
        IntSummaryStatistics stats = primes.stream().mapToInt((x) -> x).summaryStatistics();
        System.out.println("Highest prime number in List : " + stats.getMax());
        System.out.println("Lowest prime number in List : " + stats.getMin());
        System.out.println("Sum of all prime numbers : " + stats.getSum());
        System.out.println("Average of all prime numbers : " + stats.getAverage());

    }
    
    public static void main(String[] args) {
        LambdaDemo lambda = new LambdaDemo();
        //        lambda.runnable();
        //        lambda.event();
        //        lambda.foreachDemo();
        //        lambda.filter();
//        lambda.map();
        lambda.collection();
    }
}

class LambdaRunnable implements Runnable {
    
    private String name;
    
    public LambdaRunnable(String name) {
        this.name = name;
    }
    
    @Override
    public void run() {
        System.out.println("LambdaRunnable name = " + name);
    }
    
}
